package com.jwb.controller;

import com.alibaba.fastjson.JSONObject;
import com.jwb.config.security.RSAKey;
import com.jwb.config.security.SecurityEncoder;
import com.jwb.util.RSA;
import org.apache.commons.lang.StringUtils;
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.util.text.BasicTextEncryptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Controller
public class SecureLoginController {
    @Autowired
    private RSAKey rsaKey;

    @Autowired
    private RedisTemplate redisTemplate;

    @RequestMapping("/index")
    public String login(HttpServletRequest req, Model model){
        HttpSession session = req.getSession();
        if(session.getAttribute("username")!=null){
            model.addAttribute("name",(String)session.getAttribute("username"));
            session.removeAttribute("username");
        }
        if(session.getAttribute("error")!=null){
            model.addAttribute("error",(String)session.getAttribute("error"));
            session.removeAttribute("error");
        }
        model.addAttribute("key",rsaKey.getPublic_key());
        return "index";
    }

    @RequestMapping("/checkCode")
    public void checkCode(HttpServletRequest req, HttpServletResponse res){
        int width= 60, height = 50;
        int stringNum=4, lineSize=25;
        res.setContentType("text/html;charset=UTF-8");
        res.setHeader("Pragma", "No-cache");
        res.setHeader("Cache-Control", "no-cache");
        res.setDateHeader("Expire", 0);

        HttpSession session = req.getSession();

        BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_BGR);
        Graphics gs = image.getGraphics();
        Graphics2D g = (Graphics2D)gs;

        g.fillRect(0, 0, width, height);
        g.setFont(new Font("Times New Roman",Font.ROMAN_BASELINE,lineSize));
        g.setColor(getRandColor(110, 133));

        Random random = new Random();

        //绘制随机字符
        String code = "";
        double[] dd = {20 * Math.PI / 180, 345 * Math.PI / 180, 359 * Math.PI / 180,0 * Math.PI / 180};
        for(int i=0;i<stringNum;i++){
            String rand = String.valueOf(random.nextInt(10));
            code += rand;

            g.rotate(dd[i]);

            // 将认证码显示到图象中
            // 调用函数出来的颜色相同，可能是因为种子太接近，所以只能直接生成
            g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
            g.drawString(rand, 13 * i + 6, 16);
        }

        String uuid = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(uuid,code,2, TimeUnit.MINUTES);
        Cookie cookie = new Cookie("captcha",uuid);
        /*key写入cookie，验证时获取*/
        res.addCookie(cookie);
        //图像生效
        g.dispose();
        try {
            //	Base64.Encoder base64 = Base64.getEncoder();
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            ImageIO.write(image, "JPEG", output);
            //	String imgsrc = base64.encodeToString(output.toByteArray());
            BASE64Encoder encode = new BASE64Encoder();
            String imgsrc = encode.encodeBuffer(output.toByteArray());
            Map<String,Object> result = new HashMap<String, Object>();
            result.put("image_base64", imgsrc);
            res.getWriter().write(JSONObject.toJSONString(result));
            res.getWriter().close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static Color getRandColor(int fc, int bc) {
        Random random = new Random();
        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

    @PostMapping("/compareCode")
    @ResponseBody
    public String compareCode(HttpServletRequest req){
        JSONObject result = new JSONObject();
        String code = req.getParameter("code");
        Cookie[] cookies = req.getCookies();
        String uuid = "";
        for (Cookie cookie : cookies)
        {
            String cookieName = cookie.getName();
            if ("captcha".equals(cookieName))
            {
                uuid = cookie.getValue();
            }
        }
        if(StringUtils.isEmpty(uuid)||!redisTemplate.hasKey(uuid)){
            result.put("respCode","-9");
            result.put("respDesc","验证码已过期");
        }else{
            String checkcode = (String)redisTemplate.opsForValue().get(uuid);
            if(code.equalsIgnoreCase(checkcode)){
                result.put("respCode","0");
                result.put("respDesc","OK");
            }else{
                result.put("respCode","-1");
                result.put("respDesc","验证码错误");
            }
        }
        return result.toString();
    }


    @RequestMapping("/key")
    @ResponseBody
    public String key(){
        return rsaKey.getPublic_key();
    }

    @Autowired
    private StringEncryptor stringEncryptor;

    @RequestMapping("/encryptconf")
    @ResponseBody
    public String encryptconf(String text){
        return stringEncryptor.encrypt(text);
    }

    @RequestMapping("/decryptconf")
    @ResponseBody
    public String decryptconf(String text){
        return stringEncryptor.decrypt(text);
    }

    @RequestMapping("/encryptdb")
    @ResponseBody
    public String encryptdb(String password) {
        return new SecurityEncoder().encode(password);
    }

    @RequestMapping("/check")
    @ResponseBody
    public String check(){
        return "index";
    }


}
